from flask import g, redirect, render_template, request, url_for, flash

from flask_login import login_user
from redash import settings, redis_connection
from redash.authentication.org_resolving import current_org
from redash.handlers.base import routes
from redash.models import Group, Organization, User, db
from redash.tasks.general import subscribe
from wtforms import BooleanField, Form, PasswordField, StringField, validators
from wtforms.fields.html5 import EmailField

try:
    import sys
    import random
    from typing import List
    from Tea.core import TeaCore
    from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
    from alibabacloud_tea_openapi import models as open_api_models
    from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
except ImportError:
    settings.ALI_ACCESS_KEY_ID = ''


class SetupForm(Form):
    name = StringField("用户名", validators=[validators.InputRequired()])
    code = StringField("用户编码", validators=[validators.InputRequired()])
    email = EmailField("电子邮箱", validators=[validators.Email()])
    mobile = StringField("手机号码", validators=[validators.Optional()])
    if settings.ALI_ACCESS_KEY_ID !="" and settings.MULTI_ORG:
        sms = StringField("验证码", validators=[validators.Length(4)])
    password = PasswordField("密码", validators=[validators.Length(6)])
    org_name = StringField("单位名称", validators=[validators.InputRequired()])
    security_notifications = BooleanField()
    newsletter = BooleanField()
    if settings.MULTI_ORG:
        org_slug = StringField("单位代码", validators=[validators.InputRequired()])

def create_org(org_name, user_name, code, email, mobile, password, org_slug="default"):
    default_org = Organization(name=org_name, slug=org_slug, settings={})
    admin_group = Group(
        code="admin",
        name="系统管理员",
        permissions=["admin", "super_admin"],
        org=default_org,
        type=Group.BUILTIN_GROUP,
    )
    default_group = Group(
        code="default",
        name="报表设计",
        permissions=Group.DEFAULT_PERMISSIONS,
        org=default_org,
        type=Group.BUILTIN_GROUP,
    )
    audit_group = Group(
        code="audit",
        name="审核",
        permissions=["audit"],
        org=default_org,
        type=Group.BUILTIN_GROUP,
    )
    db.session.add_all([default_org, admin_group, default_group,audit_group])
    db.session.commit()

    user = User(
        org=default_org,
        name=user_name,
        code=code,
        email=email,
        mobile=mobile,
        group_ids=[admin_group.id, default_group.id],
    )
    user.hash_password(password)

    db.session.add(user)
    db.session.commit()

    return default_org, user


@routes.route("/setup", methods=["GET", "POST"])
def setup():
    if current_org != None and not settings.MULTI_ORG:
        return redirect("/")

    form = SetupForm(request.form)

    if request.method == "POST" and "smssend" in request.form:
        try:
            mobile = request.form["mobile"]
            if len(mobile) == 11:
                sms = random.randint(1000,9999)
                config = open_api_models.Config(
                    access_key_id=settings.ALI_ACCESS_KEY_ID,
                    access_key_secret=settings.ALI_ACCESS_KEY_SECRET
                )
                config.endpoint =  settings.ALI_ENDPOINT
                client = Dysmsapi20170525Client(config)
                
                jsonData = '{ "code" : "' + str(sms) + '" }'

                send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
                    phone_numbers=mobile,
                    sign_name=settings.ALI_SIGN_NAME,
                    template_code=settings.ALI_TEMPLATE_CODE,
                    template_param=jsonData
                )

                callback = client.send_sms(send_sms_request)
                redis_connection.set("dazdata_" + mobile, sms)
                redis_connection.expire("dazdata_" + mobile, 300)
                flash("验证码发送成功。")
            else:
                flash("手机号码不正确。")
        except NoResultFound:
            flash("验证码发送失败。")

        return render_template("multi_org_setup.html" if settings.MULTI_ORG else "setup.html", form=form)
    
    if request.method == "POST" and settings.MULTI_ORG and settings.ALI_ACCESS_KEY_ID !="":
        if form.sms.data == "":
            flash('请点击发送手机验证码，并输入接收到的短信验证码！', category="error")
            return render_template("multi_org_setup.html" if settings.MULTI_ORG else "setup.html", form=form)
        if form.sms.data != redis_connection.get("dazdata_" + form.mobile.data):
            flash('输入的手机短信验证码不正确或已过期，请重新发送验证码！', category="error")
            return render_template("multi_org_setup.html" if settings.MULTI_ORG else "setup.html", form=form)
  
    form.newsletter.data = True
    form.security_notifications.data = True

    if request.method == "POST" and form.validate():
        try:
            default_org, user = create_org(
                form.org_name.data, form.name.data, form.code.data, form.email.data, form.mobile.data, form.password.data,
                form.org_slug.data if settings.MULTI_ORG else "default"
            )
        except:
            flash('单位代码已被占用，请重新输入！', category="error")
            return render_template("multi_org_setup.html" if settings.MULTI_ORG else "setup.html", form=form)

        g.org = default_org
        login_user(user)

        # signup to newsletter if needed
        if form.newsletter.data or form.security_notifications:
            subscribe.delay(form.data)

        return redirect(url_for("redash.index", org_slug = form.org_slug.data if settings.MULTI_ORG else None))

    return render_template("multi_org_setup.html" if settings.MULTI_ORG else "setup.html", form=form, show_sms_login=settings.ALI_ACCESS_KEY_ID)
